package com.dabai.iot.core.event;

import com.dabai.common.core.utils.ObjectUtils;
import com.dabai.common.core.utils.StringUtils;
import com.dabai.iot.common.enums.AlarmActionType;
import com.dabai.iot.common.enums.AlarmConditionEnum;
import com.dabai.iot.common.enums.ComparatorEnum;
import com.dabai.iot.core.entity.*;
import com.dabai.iot.core.model.AlarmCheckResult;
import com.dabai.iot.core.model.AlarmTriggeredCondition;
import com.dabai.iot.core.model.AlarmTriggeredParameter;
import com.dabai.iot.core.service.*;
import com.dabai.iot.core.utils.AlarmActionUtil;
import com.dabai.iot.core.utils.AlarmChecker;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;

import java.util.List;

/**
 * TODO: 告警事件监听
 *
 * @author kev1n
 */
@Slf4j
@RequiredArgsConstructor
@Configuration(proxyBeanMethods = false)
public class AlarmEventListener {

    private final IDeviceService deviceService;
    private final IAlarmService alarmService;
    private final IAlarmListenerService alarmListenerService;
    private final IAlarmActionService alarmActionService;
    private final IAlarmRecordService alarmRecordService;

    @Async
    @EventListener(AlarmEvent.class)
    public void alarmEvent(AlarmEvent event) {
        Long deviceId = event.getDeviceId();
        String traceId = event.getTraceId();
        String reportValue = "";

        AlarmConditionEnum conditionEnum = event.getConditionEnum();
        if (AlarmConditionEnum.STATUS.equals(conditionEnum)) {
            reportValue = event.getStatusValue();
        } else {
            reportValue = event.getPropertyPayload();
        }

        checkAlarm(deviceId, traceId, conditionEnum, reportValue);
    }

    private void checkAlarm(Long deviceId, String traceId, AlarmConditionEnum conditionEnum, String reportValue) {
        DeviceEntity device = deviceService.getDeviceCacheById(deviceId);
        if (device == null) {
            return;
        }

        // 获取设备关联的告警配置列表
        List<AlarmEntity> alarmEntityList = alarmService.getAlarmListCacheByRelationDevice(deviceId);
        if (ObjectUtils.isEmpty(alarmEntityList)) {
            return;
        }

        // 一个设备可能关联了多个告警配置
        for (AlarmEntity alarmEntity : alarmEntityList) {
            Long alarmId = alarmEntity.getId();

            AlarmListenerEntity alarmListener = alarmListenerService.getAlarmListenerCacheByAlarmId(alarmId);
            if (alarmListener == null) {
                continue;
            }

            // 获取监听条件
            String conditions = alarmListener.getConditions();

            AlarmCheckResult alarmCheckResult = AlarmChecker.checkAlarm(conditionEnum, reportValue, conditions);

            // 触发了该报警条件
            if (alarmCheckResult.isAlarmTriggered()) {

                StringBuilder sb = new StringBuilder("触发告警");

                List<AlarmTriggeredCondition> triggeredConditions = alarmCheckResult.getTriggeredConditions();
                for (AlarmTriggeredCondition triggeredCondition : triggeredConditions) {

                    if (AlarmConditionEnum.PROPERTY.equals(triggeredCondition.getConditionEnum())) {
                        for (AlarmTriggeredParameter parameter : triggeredCondition.getParameters()) {

                            String desc = StringUtils.format("，上报 [{}] 的值 [{}] {}条件值 [{}]",
                                parameter.getPropertyIdentifier(), parameter.getReportValue(), ComparatorEnum.fromValue(parameter.getComparator()).getDesc(), parameter.getConditionValue());
                            sb.append(desc);

                        }
                    } else {
                        String deviceStatus = triggeredCondition.getDeviceStatus();
                        sb.append("，设备").append(deviceStatus);
                    }
                }

                log.info("触发告警，deviceId={}，traceId={}，alarmId={}, desc: {}", deviceId, traceId, alarmId, sb);

                // 1、添加告警记录
                AlarmRecordEntity alarmRecord = new AlarmRecordEntity();
                alarmRecord.setTenantId(alarmEntity.getTenantId());
                alarmRecord.setAlarmId(alarmId);
                alarmRecord.setProductId(alarmEntity.getProductId());
                alarmRecord.setDeviceId(deviceId);
                alarmRecord.setTraceId(traceId);
                alarmRecord.setDescription(sb.toString());
                alarmRecord.setCreateDept(alarmEntity.getCreateDept());
                alarmRecord.setCreateBy(alarmEntity.getCreateBy());
                alarmRecord.setUpdateBy(alarmEntity.getUpdateBy());
                alarmRecordService.save(alarmRecord);

                // TODO: 2、alarm action
                List<AlarmActionEntity> alarmActionList = alarmActionService.getAlarmActionsCacheByAlarmId(alarmId);
                if (ObjectUtils.isNotEmpty(alarmActionList)) {
                    for (AlarmActionEntity alarmAction : alarmActionList) {
                        AlarmActionType actionType = AlarmActionType.fromValue(alarmAction.getActionType());
                        switch (actionType) {
                            case SMS:
                                // TODO 短信发送

                                break;
                            case HTTP_POST:
                                AlarmActionUtil.httpPost(traceId, device, sb.toString());
                                break;
                            case WECHAT_BOT:
                                AlarmActionUtil.qyWechatPost(traceId, device, sb.toString());
                                break;
                        }
                    }
                }
            }
        }
    }

}
